<?php

defined('SYSPATH') or die('Access error!');

/**
 * Date helper类
 */
class Date
{

    const YEAR = 31556926;
    const MONTH = 2629744;
    const WEEK = 604800;
    const DAY = 86400;
    const HOUR = 3600;
    const MINUTE = 60;

    public static $timestamp_format = 'Y-m-d H:i:s';
    public static $timezone;

    /**
     * 返回两个时区之间的偏移量（以秒为单位）。使用户在不同的时区显示日期。
     *
     *     $seconds = Date::offset('America/Chicago', 'GMT');
     *
     * [!!] PHP支持的时区的列表
     * <http://php.net/timezones>.
     *
     * @param   string   
     * @param   string   
     * @param   mixed    
     * @return  integer
     */
    public static function offset($remote, $local = NULL, $now = NULL)
    {
        if ($local === NULL)
        {
            $local = date_default_timezone_get();
        }

        if (is_int($now))
        {
            $now = date(DateDate::RFC2822, $now);
        }

        $zone_remote = new DateTimeZone($remote);
        $zone_local = new DateTimeZone($local);

        $time_remote = new DateTime($now, $zone_remote);
        $time_local = new DateTime($now, $zone_local);

        $offset = $zone_remote->getOffset($time_remote) - $zone_local->getOffset($time_local);

        return $offset;
    }

    /**
     * 在一分钟内的秒数，递增的步骤。通常用作生成一个列表
     *
     *     $seconds = Date::seconds(); // 01, 02, 03, ..., 58, 59, 60
     *
     * @param   integer  
     * @param   integer 
     * @param   integer  
     * @return  array  
     */
    public static function seconds($step = 1, $start = 0, $end = 60)
    {
        $step = (int) $step;

        $seconds = array();

        for ($i = $start; $i < $end; $i += $step)
        {
            $seconds[$i] = sprintf('%02d', $i);
        }

        return $seconds;
    }

    /**
     * 在一小时内的分钟数，递增的步骤。用于产生一个列表。
     *
     *     $minutes = Date::minutes(); // 05, 10, 15, ..., 50, 55, 60
     *
     * @uses    Date::seconds
     * @param   integer  amount to increment each step by, 1 to 30
     * @return  array    A mirrored (foo => foo) array from 1-60.
     */
    public static function minutes($step = 5)
    {
        return Date::seconds($step);
    }

    /**
     *   $hours = Date::hours(); // 01, 02, 03, ..., 10, 11, 12
     * @param type $step
     * @param type $long
     * @param type $start
     * @return type 
     */
    public static function hours($step = 1, $long = FALSE, $start = NULL)
    {
        $step = (int) $step;
        $long = (bool) $long;
        $hours = array();

        if ($start === NULL)
        {
            $start = ($long === FALSE) ? 1 : 0;
        }

        $hours = array();

        $size = ($long === TRUE) ? 23 : 12;

        for ($i = $start; $i <= $size; $i += $step)
        {
            $hours[$i] = (string) $i;
        }

        return $hours;
    }

    /**
     * 根据所给的小时 返回 AM or PM, 
     *
     *     $type = Date::ampm(12); // PM
     *     $type = Date::ampm(1);  // AM
     *
     * @param   integer 
     * @return  string
     */
    public static function ampm($hour)
    {
        // Always integer
        $hour = (int) $hour;

        return ($hour > 11) ? 'PM' : 'AM';
    }

    /**
     *  $hour = Date::adjust(3, 'pm'); // 15
     * @param type $hour
     * @param type $ampm
     * @return type 
     */
    public static function adjust($hour, $ampm)
    {
        $hour = (int) $hour;
        $ampm = strtolower($ampm);

        switch ($ampm)
        {
            case 'am':
                if ($hour == 12)
                {
                    $hour = 0;
                }
                break;
            case 'pm':
                if ($hour < 12)
                {
                    $hour += 12;
                }
                break;
        }

        return sprintf('%02d', $hour);
    }

    /**
     * 根据所给的月和年返回 所有的天
     *
     *     Date::days(4, 2010); // 1, 2, 3, ..., 28, 29, 30
     * @staticvar type $months
     * @param type $month
     * @param type $year
     * @return type 
     */
    public static function days($month, $year = FALSE)
    {
        static $months;

        if ($year === FALSE)
        {
            $year = date('Y');
        }

        $month = (int) $month;
        $year = (int) $year;

        if (empty($months[$year][$month]))
        {
            $months[$year][$month] = array();

            $total = date('t', mktime(1, 0, 0, $month, 1, $year)) + 1;

            for ($i = 1; $i < $total; $i++)
            {
                $months[$year][$month][$i] = (string) $i;
            }
        }

        return $months[$year][$month];
    }

    /**
     * 返回一年的月份（用在form中比较方便）
     *
     *     Date::months(); // 01, 02, 03, ..., 10, 11, 12
     *
     * @return  array 
     */
    public static function months()
    {
        return Date::hours();
    }

    /**
     * 返回所给定的时间的一个范围，假如没有给定。将返回当前年的前五年和后五年
     *
     *     $years = Date::years(2000, 2010); // 2000, 2001, ..., 2009, 2010
     *
     * @param   integer  
     * @param   integer  
     * @return  array
     */
    public static function years($start = FALSE, $end = FALSE)
    {
        $start = ($start === FALSE) ? (date('Y') - 5) : (int) $start;
        $end = ($end === FALSE) ? (date('Y') + 5) : (int) $end;

        $years = array();

        for ($i = $start; $i <= $end; $i++)
        {
            $years[$i] = (string) $i;
        }

        return $years;
    }

    /**
     * 返回两个时间戳之前的时差
     *
     *     $span = Date::span(60, 182, 'minutes,seconds'); 
     *     $span = Date::span(60, 182, 'minutes'); 
     * @param type $remote
     * @param type $local
     * @param type $output
     * @return boolean 
     */
    public static function span($remote, $local = NULL, $output = 'years,months,weeks,days,hours,minutes,seconds')
    {
        $output = trim(strtolower((string) $output));

        if (!$output)
        {
            return FALSE;
        }

        $output = preg_split('/[^a-z]+/', $output);

        $output = array_combine($output, array_fill(0, count($output), 0));

        extract(array_flip($output), EXTR_SKIP);

        if ($local === NULL)
        {
            $local = time();
        }

        $timespan = abs($remote - $local);

        if (isset($output['years']))
        {
            $timespan -= Date::YEAR * ($output['years'] = (int) floor($timespan / Date::YEAR));
        }

        if (isset($output['months']))
        {
            $timespan -= Date::MONTH * ($output['months'] = (int) floor($timespan / Date::MONTH));
        }

        if (isset($output['weeks']))
        {
            $timespan -= Date::WEEK * ($output['weeks'] = (int) floor($timespan / Date::WEEK));
        }

        if (isset($output['days']))
        {
            $timespan -= Date::DAY * ($output['days'] = (int) floor($timespan / Date::DAY));
        }

        if (isset($output['hours']))
        {
            $timespan -= Date::HOUR * ($output['hours'] = (int) floor($timespan / Date::HOUR));
        }

        if (isset($output['minutes']))
        {
            $timespan -= Date::MINUTE * ($output['minutes'] = (int) floor($timespan / Date::MINUTE));
        }

        if (isset($output['seconds']))
        {
            $output['seconds'] = $timespan;
        }

        if (count($output) === 1)
        {
            return array_pop($output);
        }

        return $output;
    }
    
    /**
     *  增加天数
     *
     * @param     int  $ntime  当前时间
     * @param     int  $aday   增加天数
     * @return    int
     */
    public static function add_day($ntime, $aday)
    {
        $dayst = 3600 * 24;
        $oktime = $ntime + ($aday * $dayst);
        return $oktime;
    }

    /**
     *  减去时间
     *
     * @param     int  $ntime  当前时间
     * @param     int  $ctime  减少的时间
     * @return    int
     */
    public static function sub_day($ntime, $ctime)
    {
        $dayst = 3600 * 24;
        $cday = ceil(($ntime - $ctime) / $dayst);
        return $cday;
    }

    /**
     *   日期的距离输出
     *  
     * @param type $timestamp
     * @param type $dateformat
     * @return string
     */
    public static function floortime($timestamp, $dateformat = 3)
    {
        if (empty($timestamp))
        {
            $timestamp = Date::get_time();
        }
        $time = Date::get_time() - $timestamp;
        if ($time > 24 * 3600)
        {
            $result = Date::timeformat($timestamp, $dateformat);
        }
        elseif ($time > 3600)
        {
            $result = intval($time / 3600) . '小时前';
        }
        elseif ($time > 60)
        {
            $result = intval($time / 60) . '分前';
        }
        elseif ($time > 0)
        {
            $result = $time . '秒前';
        }
        else
        {
            $result = '刚刚';
        }
        return $result;
    }

    /**
     * 从普通时间转换为Linux时间截
     *
     * @param     string   $dtime  普通时间
     * @return    string
     */
    public static function get_mk_time($dtime)
    {
        if (!preg_match("/[^0-9]/", $dtime))
        {
            return $dtime;
        }
        $dtime = trim($dtime);
        $dt = Array(1970, 1, 1, 0, 0, 0);
        $dtime = preg_replace("/[\r\n\t]|日|秒/", " ", $dtime);
        $dtime = str_replace("年", "-", $dtime);
        $dtime = str_replace("月", "-", $dtime);
        $dtime = str_replace("时", ":", $dtime);
        $dtime = str_replace("分", ":", $dtime);
        $dtime = trim(preg_replace("/[ ]{1,}/", " ", $dtime));
        $ds = explode(" ", $dtime);
        $ymd = explode("-", $ds[0]);
        if (!isset($ymd[1]))
        {
            $ymd = explode(".", $ds[0]);
        }
        if (isset($ymd[0]))
        {
            $dt[0] = $ymd[0];
        }
        if (isset($ymd[1]))
            $dt[1] = $ymd[1];
        if (isset($ymd[2]))
            $dt[2] = $ymd[2];
        if (strlen($dt[0]) == 2)
            $dt[0] = '20' . $dt[0];
        if (isset($ds[1]))
        {
            $hms = explode(":", $ds[1]);
            if (isset($hms[0]))
                $dt[3] = $hms[0];
            if (isset($hms[1]))
                $dt[4] = $hms[1];
            if (isset($hms[2]))
                $dt[5] = $hms[2];
        }
        foreach ($dt as $k => $v)
        {
            $v = preg_replace("/^0{1,}/", '', trim($v));
            if ($v == '')
            {
                $dt[$k] = 0;
            }
        }
        $mt = mktime($dt[3], $dt[4], $dt[5], $dt[1], $dt[2], $dt[0]);
        if (!empty($mt))
        {
            return $mt;
        }
        else
        {
            return time();
        }
    }

    /**
     * 获取当前星期
     * 
     * @param $timestamp
     */
    public static function current_week($timestamp)
    {
        $times = intval($timestamp);
        if (!$times)
            return true;
        $weekarray = array('星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六');
        return $weekarray[date("w", $timestamp)];
    }

    /**
     *  格式化输出时间
     * 
     * @param type $time
     * @param type $type
     * @param type $font
     * @param type $ddstr
     * @return type
     */
    public static function timeformat($time, $type = 3, $font = '-', $ddstr = 'Y')
    {

        $time = empty($time) ? Date::get_time() : ((strstr($time, ':') || strstr($time, '-')) ? strtotime($time) : $time);
        switch ($type)
        {
            case 1:
                $format = date('H:i:s', $time);
                break;
            case 2:
                $format = date('Y' . $font . 'm' . $font . 'd', $time);
                break;
            case 3:
                $format = date('Y' . $font . 'm' . $font . 'd H:i:s', $time);
                break;
            case 4:
                $format = date('Y' . $font . 'm' . $font . 'd H:i', $time);
                break;
            case 5:
                $format = date('m' . $font . 'd H:i', $time);
                break;
            case 6:
                $format = date('m' . $font . 'd', $time);
                break;
            case 7:
                $format = date('y' . $font . 'm' . $font . 'd', $time);
                break;
            case 8:
                $format = date('y' . $font . 'm' . $font . 'd H:i:s', $time);
                break;
            case 9:
                $format = date('y' . $font . 'm' . $font . 'd H:i', $time);
                break;
            case 10:
                $format = date($ddstr, $time);
                break;
        }
        return $format;
    }

    public static function get_time()
    {
        return time();
    }

}
